/*
    Copyright 2006-2012 Patrik Jonsson, sunrise@familjenjonsson.org

    This file is part of Sunrise.

    Sunrise is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    Sunrise is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Sunrise.  If not, see <http://www.gnu.org/licenses/>.

*/

/** \file

    Definition of the refinement_accuracy_data class
    template. \ingroup makegrid */

#ifndef __refinement_accuracy_data__
#define __refinement_accuracy_data__

#include "mono_poly_abstract.h"

namespace mcrx {
  template<typename> class refinement_accuracy_data;
};

/** Keeps information about the grid refinement accuracy when creating
    the grid. The mean and variance of the quantities in a subtree are
    described by this, so a decision can be made whether the subtree
    can be unified or not. This is used by both the nbody_data_grid
    and the grid factory classes.  \ingroup mcrx */
template <typename data_type>
class mcrx::refinement_accuracy_data {
public:
  typedef data_type T_data;

  T_data sum; ///< Sum of quantities.
  T_data sumsq; ///< Sum of squares of quantities.
  int n; ///< Number of terms in the sum.
  bool all_leaves; ///< True if all cells are leaf cells.

  refinement_accuracy_data() : sum(), sumsq(), n(0), all_leaves(false) {};

  refinement_accuracy_data (const T_data& s, const T_data& ssq, 
			    int nn, bool al):
    sum (s), sumsq (ssq),
    n (nn), all_leaves (al) {}; 

  /** Copy constructor makes reference copies of the data members, if
      applicable. */
  refinement_accuracy_data (const refinement_accuracy_data& rhs) :
    sum(rhs.sum), sumsq(rhs.sumsq), n(rhs.n), all_leaves(rhs.all_leaves) {};

  /** Increment operator is used to accumulate over cells about to be
      unified. Note that all_leaves is AND'ed together. */
  refinement_accuracy_data& operator+= (const refinement_accuracy_data& rhs) {
    sum += rhs.sum; sumsq += rhs.sumsq; n+= rhs.n; all_leaves &= rhs.all_leaves;
    return *this;};

  /** Assignment operator makes independent_copies of the data
      elements to ensure we don't propagate reference copies. */
  refinement_accuracy_data& operator=(const refinement_accuracy_data& rhs) {
    assign(sum, rhs.sum);
    assign(sumsq, rhs.sumsq);
    n=rhs.n; all_leaves=rhs.all_leaves;
    return *this;
  };
};

#endif
